package org.springframework.aop.framework.autoproxy;

import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.A17.Aspect1;
import org.springframework.aop.framework.autoproxy.A17.Config;
import org.springframework.aop.framework.autoproxy.A17.Target1;
import org.springframework.aop.framework.autoproxy.A17.Target2;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.Order;

public class A17_0 {
    public static void main(String[] args) {
    	GenericApplicationContext context = new GenericApplicationContext();
		context.registerBean("aspect1", Aspect1.class);
		context.registerBean("config", Config.class);
		context.registerBean(ConfigurationClassPostProcessor.class);// 加后处理器 解决@bean
		context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);// 解决切面的配置
		context.refresh();
		AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
		Object o1 = creator.wrapIfNecessary(new Target1(), "target1", "target1");//第一个参数重要  第二三参数不重要 可以随意设置
		Object o2 = creator.wrapIfNecessary(new Target2(), "target2", "target2");
		((Target1) o1).foo();
      
    }

    static class Target1 {
        public void foo() {
            System.out.println("target1 foo");
        }
    }

    static class Target2 {
        public void bar() {
            System.out.println("target2 bar");
        }
    }

    @Aspect // 高级切面类
    @Order(2)
    static class Aspect1 {
        @Before("execution(* foo())")
        public void before1() {
            System.out.println("aspect1 before1...");
        }

        @Before("execution(* foo())")
        public void before2() {
            System.out.println("aspect1 before2...");
        }
    }

    @Configuration
    static class Config {
         @Bean // 低级切面
        public Advisor advisor3(MethodInterceptor advice3) {
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution(* foo())");
            DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice3);
            advisor.setOrder(1);//设置排序
            return advisor;
        }
        @Bean
        public MethodInterceptor advice3() {
            return invocation -> {
                System.out.println("advice3 before     ...");
                Object result = invocation.proceed();
                System.out.println("advice3 after     ...");
                return result;
            };
        } 
    }

}